namespace OX.Strongbind.Dynamic
{
    using Castle.Core.Interceptor;
    using Castle.DynamicProxy;
    using System;
    using System.Collections.Generic;
    using System.Reflection;
    using OX.Strongbind.Remoting;

    internal class CrossDomainProxyGenerator : MarshalByRefObject, IProxyGenerator
    {
        ProxyGenerator generator;
        private Dictionary<object, CrossDomainProxyInterceptor> interceptors;        

        public CrossDomainProxyGenerator()
        {
            generator = new ProxyGenerator();
            interceptors = new Dictionary<object, CrossDomainProxyInterceptor>();
        }

        public T For<T>(Guid identity, IPropertyAccessNotifier notifier)
        {
            Type type = typeof(T);
            return (T)For(type, identity, notifier);
        }

        public object For(Type type, Guid identity, IPropertyAccessNotifier notifier)
        {
            if (type.IsInterface)
            {
                ProxyGenerationOptions generationOptions = new ProxyGenerationOptions();
                generationOptions.BaseTypeForInterfaceProxy = typeof(MarshalByRefObject);

                CrossDomainProxyInterceptor interceptor = new CrossDomainProxyInterceptor(this, identity, notifier);

                object instance = generator.CreateInterfaceProxyWithoutTarget(type, new Type[0],
                    generationOptions, interceptor);

                interceptors.Add(instance, interceptor);

                return instance;
            }
            else
            {
                throw new InvalidOperationException("The object to proxy must be an interface");
            }
        }
    }
}
